﻿// author : David Janacek, dj-soft@seznam.cz, 2013-12-13
// company: Asseco Solution, a.s. CZ
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace Noris.Tools.QCode.Common
{
    #region class QMatrix - PaintTo(), ToBitmap()
    public partial class QMatrix
    {
        #region PaintTo() : vykreslí matrix do grafiky
        /// <summary>
        /// Vykreslí daný kód skrz danou grafiku do uvedeného prostoru, v daných barvách.
        /// Vrací true = OK / false = chyba (typicky malý prostor).
        /// </summary>
        /// <param name="graphics"></param>
        /// <param name="area"></param>
        /// <param name="colorLight"></param>
        /// <param name="colorDark"></param>
        /// <returns></returns>
        public bool PaintCodeTo(Graphics graphics, Rectangle area, Color colorLight, Color colorDark)
        {
            // Výpočet velikosti jednoho bodu:
            int moduleWidth = 0;
            Size clientSize = area.Size;
            int minDim = (clientSize.Width < clientSize.Height ? clientSize.Width : clientSize.Height);
            if (minDim <= 0) return false;
            int matrixSize = this.Width;
            moduleWidth = minDim / matrixSize;
            if (moduleWidth <= 0) return false;

            // Určení prostoru, který reálně obsadí kód:
            int codeDim = moduleWidth * matrixSize;
            int x = (clientSize.Width - codeDim) / 2;
            int y = (clientSize.Height - codeDim) / 2;
            Rectangle codeArea = new Rectangle(area.X + x, area.Y + y, codeDim, codeDim);

            // Kreslení:
            using (SolidBrush brush = new SolidBrush(colorLight))
            {
                if (!colorLight.IsEmpty)
                    graphics.FillRectangle(brush, codeArea);

                brush.Color = colorDark;

                int i = 0;  // Logická dimenze ve směru X
                int j = 0;  // Logická dimenze ve směru Y
                int fd = codeArea.Width;                             // Fyzický rozměr. Šířka i výška jsou shodné.
                for (int fy = 0; fy < fd; fy += moduleWidth)         // Souřadnice Y jde odshora, v krocích podle velikosti "bodu" (mw)
                {
                    i = 0;
                    for (int fx = 0; fx < fd; fx += moduleWidth)
                    {
                        if (this[i, j] == '1')
                        {   // Kreslit budu jen černé body:
                            Rectangle point = new Rectangle(codeArea.X + fx, codeArea.Y + fy, moduleWidth, moduleWidth);
                            graphics.FillRectangle(brush, point);
                        }
                        i++;
                    }
                    j++;
                }
            }
            return true;
        }
        #endregion
        #region Export QR kódu do bitmapy
        /// <summary>
        /// Vrátí obrázek obsahující tento QR kód, vykreslený v dané velikosti bitmapy.
        /// </summary>
        /// <param name="size">Velikost bitmapy v pixelech. Namísto velikosti je možno zadat počet pixelů na jeden datový bod (čtvereček).</param>
        /// <returns></returns>
        public Bitmap ToBitmap(Size size)
        {
            return this._ToBitmap(size, 300f, Color.LightGray, Color.White, Color.Black);
        }
        /// <summary>
        /// Vrátí obrázek obsahující tento QR kód, vykreslený v dané velikosti bitmapy a s daným rozlišením (jde jen o údaj o rozlišení, nemá vliv na skutečnou velikost čtverečku kódu).
        /// </summary>
        /// <param name="size">Velikost bitmapy v pixelech. Namísto velikosti je možno zadat počet pixelů na jeden datový bod (čtvereček).</param>
        /// <param name="resolutionDPI">Rozlišení bitmapy, určuje fyzickou velikost v mm (kdežto zadaná velikost size je v pixelech)</param>
        /// <returns></returns>
        public Bitmap ToBitmap(Size size, float resolutionDPI)
        {
            return this._ToBitmap(size, resolutionDPI, Color.LightGray, Color.White, Color.Black);
        }
        /// <summary>
        /// Vrátí obrázek obsahující tento QR kód, vykreslený v dané velikosti bitmapy a s daným rozlišením (jde jen o údaj o rozlišení, nemá vliv na skutečnou velikost čtverečku kódu).
        /// Lze zadat barvy okolí kódu (běžně šedá), barvu podkladu (běžně bílá) a barvu kódu (běžně černá).
        /// </summary>
        /// <param name="size">Velikost bitmapy v pixelech. Namísto velikosti je možno zadat počet pixelů na jeden datový bod (čtvereček).</param>
        /// <param name="resolutionDPI">Rozlišení bitmapy, určuje fyzickou velikost v mm (kdežto zadaná velikost size je v pixelech)</param>
        /// <param name="grayColor">Barva okolí kódu, výchozí je Color.LightGray</param>
        /// <param name="whiteColor">Barva pozadí kódu, výchozí je Color.White</param>
        /// <param name="blackColor">Barva kódu, výchozí je Color.Black</param>
        /// <returns></returns>
        public Bitmap ToBitmap(Size size, float resolutionDPI, Color grayColor, Color whiteColor, Color blackColor)
        {
            return this._ToBitmap(size, resolutionDPI, grayColor, whiteColor, blackColor);
        }
        /// <summary>
        /// Vrátí obrázek obsahující tento QR kód, vykreslený v dané velikosti bitmapy.
        /// </summary>
        /// <param name="moduleSize">Počet grafických pixelů na jeden datový bod (čtvereček). Alternativně je možno zadat cílovou velikost bitmapy, do které se kód umístí.</param>
        /// <returns></returns>
        public Bitmap ToBitmap(int moduleSize)
        {
            return this._ToBitmap(moduleSize, 300f, Color.LightGray, Color.White, Color.Black);
        }
        /// <summary>
        /// Vrátí obrázek obsahující tento QR kód, vykreslený v dané velikosti bitmapy a s daným rozlišením (jde jen o údaj o rozlišení, nemá vliv na skutečnou velikost čtverečku kódu).
        /// </summary>
        /// <param name="moduleSize">Počet grafických pixelů na jeden datový bod (čtvereček). Alternativně je možno zadat cílovou velikost bitmapy, do které se kód umístí.</param>
        /// <param name="resolutionDPI">Rozlišení bitmapy, určuje fyzickou velikost v mm (kdežto zadaná velikost size je v pixelech)</param>
        /// <returns></returns>
        public Bitmap ToBitmap(int moduleSize, float resolutionDPI)
        {
            return this._ToBitmap(moduleSize, resolutionDPI, Color.LightGray, Color.White, Color.Black);
        }
        /// <summary>
        /// Vrátí obrázek obsahující tento QR kód, vykreslený v dané velikosti bitmapy a s daným rozlišením (jde jen o údaj o rozlišení, nemá vliv na skutečnou velikost čtverečku kódu).
        /// Lze zadat barvy okolí kódu (běžně šedá), barvu podkladu (běžně bílá) a barvu kódu (běžně černá).
        /// </summary>
        /// <param name="moduleSize">Počet grafických pixelů na jeden datový bod (čtvereček). Alternativně je možno zadat cílovou velikost bitmapy, do které se kód umístí.</param>
        /// <param name="resolutionDPI">Rozlišení bitmapy, určuje fyzickou velikost v mm (kdežto zadaná velikost size je v pixelech)</param>
        /// <param name="grayColor">Barva okolí kódu, výchozí je Color.LightGray</param>
        /// <param name="whiteColor">Barva pozadí kódu, výchozí je Color.White</param>
        /// <param name="blackColor">Barva kódu, výchozí je Color.Black</param>
        /// <returns></returns>
        public Bitmap ToBitmap(int moduleSize, float resolutionDPI, Color grayColor, Color whiteColor, Color blackColor)
        {
            return this._ToBitmap(moduleSize, resolutionDPI, grayColor, whiteColor, blackColor);
        }
        private Bitmap _ToBitmap(int moduleSize, float resolutionDPI, Color grayColor, Color whiteColor, Color blackColor)
        {
            Size size = this._GetSizeForModuleSize(moduleSize);
            return this._ToBitmap(size, resolutionDPI, grayColor, whiteColor, blackColor);
        }
        private Bitmap _ToBitmap(Size size, float resolutionDPI, Color grayColor, Color whiteColor, Color blackColor)
        {
            Bitmap bmp = new Bitmap(size.Width, size.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            bmp.SetResolution(resolutionDPI, resolutionDPI);

            Rectangle area = new Rectangle(0, 0, size.Width, size.Height);
            using (Graphics graphics = Graphics.FromImage(bmp))
            {
                graphics.Clear(grayColor);
                this.PaintCodeTo(graphics, area, whiteColor, blackColor);
            }

            return bmp;
        }
        /// <summary>
        /// Vrátí velikost obrázku (Size v pixelech), kterou musí mít, aby aktuální kód vykreslil s danou velikostí jednoho QR bodu (počet pixelů na čtvereček)
        /// </summary>
        /// <param name="moduleSize">Velikost jednoho QR bodu (počet pixelů na čtvereček)</param>
        /// <returns></returns>
        private Size _GetSizeForModuleSize(int moduleSize)
        {
            int codeDim = this.Width * moduleSize;
            return new Size(codeDim, codeDim);
        }
        /// <summary>
        /// Vrátí System.Drawing.Imaging.ImageFormat odpovídající příponě jména souboru.
        /// Pracuje pouze pro přípony BMP, FIG, JPG, JPEG, PNG, TIF, TIFF. Implicitní je GIF.
        /// Ostatní formáty nevrací, protože nejsou kompatibilní s kreslením pixelů pomocí třídy Bitmap.
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static System.Drawing.Imaging.ImageFormat GetImageFormatFromName(string name)
        {
            string ext = System.IO.Path.GetExtension(name).ToLower();
            switch (ext)
            {
                case ".bmp": return System.Drawing.Imaging.ImageFormat.Bmp;
                // case ".emf": return System.Drawing.Imaging.ImageFormat.Emf;
                // case ".exif": return System.Drawing.Imaging.ImageFormat.Exif;
                case ".gif": return System.Drawing.Imaging.ImageFormat.Gif;
                // case ".ico": return System.Drawing.Imaging.ImageFormat.Icon;
                case ".jpg": return System.Drawing.Imaging.ImageFormat.Jpeg;
                case ".jpeg": return System.Drawing.Imaging.ImageFormat.Jpeg;
                case ".png": return System.Drawing.Imaging.ImageFormat.Png;
                case ".tif": return System.Drawing.Imaging.ImageFormat.Tiff;
                case ".tiff": return System.Drawing.Imaging.ImageFormat.Tiff;
                // case ".wmf": return System.Drawing.Imaging.ImageFormat.Wmf;
            }
            return System.Drawing.Imaging.ImageFormat.Gif;
        }
        #endregion
    }
    #endregion
}
